<?php

namespace App\Exceptions;

use Exception;
use Illuminate\Database\QueryException;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
use Tymon\JWTAuth\Exceptions\JWTException;
use Tymon\JWTAuth\Exceptions\TokenBlacklistedException;
use Tymon\JWTAuth\Exceptions\TokenExpiredException;
use Tymon\JWTAuth\Exceptions\TokenInvalidException;

class Handler extends ExceptionHandler
{
    /**
     * A list of the inputs that are never flashed for validation exceptions.
     *
     * @var array
     */
    protected $dontFlash = [
        'password',
        'password_confirmation',
    ];
    /**
     * A list of the exception types that are not reported.
     *
     * @var array
     */
    protected $dontReport = [
        //
    ];

    /**
     * Render an exception into an HTTP response.
     *
     * @param  \Illuminate\Http\Request $request
     * @param  \Exception $exception
     * @return \Illuminate\Http\Response
     */
    public function render($request, Exception $exception)
    {
        if ($exception instanceof TokenExpiredException) {
            $status_code = $exception->getMessage() == 'Token has expired and can no longer be refreshed' ? 403 : 401;
            return response_with_message($exception->getMessage(), $status_code);
        } else if ($exception instanceof TokenInvalidException // access_token 已经失效了。
            || $exception instanceof TokenBlacklistedException // 使用刷新过的旧 access_token。
            || ($exception instanceof JWTException && $exception->getMessage() == 'Token could not be parsed from the request.') // 刷新时没有提供 access_token。
            || $exception instanceof UnauthorizedHttpException // 没有提供 access_token。
        ) {
            return response_with_message($exception->getMessage(), 403);
        } else if ($exception instanceof MethodNotAllowedHttpException) {
            return response_with_message($exception->getMessage() ? $exception->getMessage() : 'Method not allowed', 500);
        } else if ($exception instanceof NotFoundHttpException) {
            return response_with_message($exception->getMessage() ? $exception->getMessage() : 'Route not found', 404);
        } else if ($exception instanceof QueryException) {
            $message = $exception->getMessage();
            $message = substr($message, 0, strpos($message, '('));
            return response_with_message($message, 500);
        } elseif ($exception instanceof HttpException || $exception instanceof ApiException) {
            $return['message'] = $exception->getMessage();
            if ($exception->getCode() !== null) {
                $return['code'] = $exception->getCode();
            }
            if (method_exists($exception, 'getExtra') && $exception->getExtra() != null) {
                $return = array_merge($return, $exception->getExtra());
            }
            return response()->json($return, $exception->getStatusCode());
        } else {
            return response_with_message($exception->getMessage(), 500);
        }
    }

    public function report(Exception $exception)
    {
        parent::report($exception);
    }
}
